#include "driver_Mobvoi_includes.h"
#include "app_Mobvoi_includes.h"
#include "Mobvoi_external.h"
#include "tc_interface.h"
#include "tra_hcit.h"
#include "tc_const.h"
#include "app_debug.h"
#include "bt_at_types.h"

#if (CONFIG_APP_MP3PLAYER == 1)
extern uint8_t mp3_need_pause;
#endif

#if (CONFIG_CTRL_BQB_TEST_SUPPORT == 1)
extern uint32_t XVR_reg_0x24_save;
static uint8_t RF_DUT_MODE = 0;
uint8_t app_get_power_level(uint8_t index)
{
    uint8_t level = 0;
    if (RF_DUT_MODE == 2)
        level = (uint8_t)((uint32_t)(XVR_reg_0x24_save & (0x0f << 8)) >> 8);
    else
        level = 0x06;
    switch (index)
    {
    case 0:
        level = 2;
        break;
    case 1:
        level = 4;
        break;
    default:
        break;
    }
    return level;
}

extern void M510_RF_Dut_ReWrite(uint8_t option);
void app_bt_enable_dut_mode(int8_t enable)
{
    app_handle_t app_h = app_get_sys_handler();

    if (app_h->unit == NULL)
        return;

    app_sleep_func(0);
    if (enable)
    {
        app_set_crystal_calibration(1);

        if (app_bt_flag1_get(APP_FLAG_DUT_MODE_ENABLE))
            return;

        //app_env_rf_pwr_set(0);
        RF_DUT_MODE = enable;
        M510_RF_Dut_ReWrite(RF_DUT_MODE); // dut mode

        if (hci_get_acl_link_count(app_h->unit) && (app_bt_flag1_get(APP_AUDIO_FLAG_SET)))
        {
            app_button_match_action();
            app_bt_flag1_set(APP_FLAG_DUT_MODE_ENABLE, 1);
        }
        else
        {
            result_t err;
            err = bt_unit_disable(app_h->unit);
            if (UWE_BUSY != err)
                app_bt_flag1_set(APP_FLAG_DUT_MODE_ENABLE, 1);
        }
    }
    else
    {
        M510_wdt_reset();
    }

    return;
}
#endif

void app_bt_enable_fcc_mode(int8_t mode, uint8_t chnl)
{
    uint32_t v;
    app_sleep_func(0);
    app_handle_t app_h = app_get_sys_handler();
    if (app_h->unit == NULL)
        return;
    if (mode > 0)
    {
        app_bt_flag1_set(APP_FLAG_FCC_MODE_ENABLE, 1);
        bt_unit_set_scan_enable(app_h->unit, 0);
        bt_unit_disable(app_h->unit);
        SYSirq_Unmask_Interrupt(&v, 1 << VIC_IDX_CEVA);
        v = REG_XVR_0x24;
        v = v & 0xFFFFFF80;
        chnl = chnl + 2;
        v = v | (chnl);
        REG_XVR_0x24 = v;
        REG_XVR_0x25 = 0;
        os_delay_ms(1);
        REG_XVR_0x08 = 0xD0005000;
        REG_XVR_0x07 = 0xFEEDC000;
        REG_XVR_0x38 |= (1 << 10); // close agc
        switch (mode)
        {
        case 1: //PN9 GFSK
            //REG_XVR_0x01 = 0xf10401b0;
            //M510_XVR_REG_0x04 = 0x58e45844;
            //M510_XVR_REG_0x09 = 0x03fff0aa;
            REG_XVR_0x25 = 0x00003800;
            break;
        case 2: //PN9 EDR2
            //REG_XVR_0x01 = 0xf10401b0;
            //M510_XVR_REG_0x04 = 0x58e45844;
            //M510_XVR_REG_0x09 = 0x03fff0aa;
            REG_XVR_0x25 = 0x00007800;
            break;
        case 3: //PN9 EDR3
            //REG_XVR_0x01 = 0xf10401b0;
            //M510_XVR_REG_0x04 = 0x58e45844;
            //M510_XVR_REG_0x09 = 0x03fff0aa;
            REG_XVR_0x25 = 0x0000B800;
            break;
        case 4: //CW
            //REG_XVR_0x01 = 0xf10401b0;
            //M510_XVR_REG_0x04 = 0x58e45844;
            //M510_XVR_REG_0x09 = 0x03fff0aa;
            REG_XVR_0x25 = 0x00003000;
            break;
        case 5: //PN9 GFSK rcv
            //REG_XVR_0x01 = 0xf10401b0;
            //M510_XVR_REG_0x04 = 0x58e45844;
            //M510_XVR_REG_0x09 = 0x03fff0aa;
            REG_XVR_0x22 &= ~(1 << 31); // close auto-syncword

            REG_XVR_0x25 = 0x00002400;
            break;
        case 6: //PN9 EDR2 rcv
            //REG_XVR_0x01 = 0xf10401b0;
            //M510_XVR_REG_0x04 = 0x58e45844;
            //M510_XVR_REG_0x09 = 0x03fff0aa;
            //M510_XVR_REG_0x20 = ;

            REG_XVR_0x25 = 0x00006400;
            break;
        case 7: //PN9 EDR3 rcv
            //REG_XVR_0x01 = 0xf10401b0;
            //M510_XVR_REG_0x04 = 0x58e45844;
            //M510_XVR_REG_0x09 = 0x03fff0aa;
            REG_XVR_0x25 = 0x0000A400;
            break;
        default:
            M510_set_clock(CPU_CLK_XTAL, 0);
            break;
        }
#if 0
		os_delay_ms(1);
		if(enable > 1) /* PN9 test mode */
			REG_XVR_0x25 = (0x1<<11)|(0x1<<12) | (0x1<<13);
		else		   /* single carrior test mode */
			REG_XVR_0x25 = (0x1<<12) | (0x1<<13);
#endif
        os_printf("Enter FCC testmode !!!\r\n");
        /* add other code */
    }
    else
    {
        M510_wdt_reset();
    }
}

uint8_t app_check_bt_mode(uint8_t mode)
{
    app_env_handle_t env_h = app_env_get_handle();
    return (env_h->env_cfg.feature.bt_mode) & mode;
}

uint8_t get_bt_dev_priv_work_flag(void)
{
    uint32_t hf_flag = 0, a2dp_flag = 0;
    uint8_t i;
    for (i = 0; i < BT_MAX_AG_COUNT; i++)
    {
        hf_flag = get_hf_priv_flag(i, APP_FLAG2_HFP_INCOMING | APP_FLAG_HFP_OUTGOING);
        a2dp_flag = get_a2dp_priv_flag(i, APP_BUTTON_FLAG_PLAY_PAUSE | APP_FLAG_MUSIC_PLAY);
        if (hf_flag && a2dp_flag)
            return 1;
    }
    return 0;
}

void sd_start_task()
{
#ifdef BT_SD_MUSIC_COEXIST
    {
        os_printf("mp3_init_coexist\r\n");
#ifdef CONFIG_APP_AEC
        app_aec_uninit();
#endif

        sbc_target_deinit_jfree_buff();

        app_player_init(1);

        os_printf("SD_Fs_Init\r\n");
        if (SD_Fs_Init())
        {
            os_printf("SD Init Err!!!\r\n");
            msg_put(MSG_SD_READ_ERR);
            return;
        }
        os_printf("player_start_first_running\r\n");
        player_start_first_running();
    }
#else
#if (CONFIG_APP_MP3PLAYER == 1)
    if ((get_app_mode() == SYS_WM_SD_MUSIC_MODE) && (!app_bt_flag1_get(APP_AUDIO_FLAG_SET)))
    {
        os_printf("BT is inactive!!!!!!!!!!!!!!!!!!!!!!!!\r\n");

#ifdef CONFIG_APP_AEC
        app_aec_uninit();
#endif

        sbc_target_deinit_jfree_buff();
        app_player_init(1);

        if (SD_Fs_Init())
        {
            os_printf("SD Init Err!!!\r\n");
            msg_put(MSG_SD_READ_ERR);
            return;
        }
        player_start_first_running();
    }
    else
    {
        os_printf("BT is still active\r\n");
    }
#endif /* CONFIG_APP_MP3PLAYER */
#endif
}

void system_mode_shift_for_sd_change(void)
{
#ifdef CONFIG_APP_SDCARD
    app_handle_t app_h = app_get_sys_handler();

    jtask_stop(app_h->app_common_task);

    if (!sd_is_attached())
    {
        if (app_h->sys_work_mode == SYS_WM_SD_MUSIC_MODE)
        {
            app_h->sys_work_mode = SYS_WM_BT_MODE;

            exit_work_mode(SYS_WM_SD_MUSIC_MODE);
            enter_mode_wave_and_action(app_h->sys_work_mode, enter_work_mode);
        }
    }
    else
    {
        switch (app_h->sys_work_mode)
        {
        case SYS_WM_BT_MODE:
            exit_work_mode(SYS_WM_BT_MODE);
            app_h->sys_work_mode = SYS_WM_SD_MUSIC_MODE;
            break;

#ifdef CONFIG_APP_USB_DISK
        case SYS_WM_UDISK_MODE:
            os_printf("enter mp3 mode from UDISK MODE\r\n");
            app_h->sys_work_mode = SYS_WM_SD_MUSIC_MODE;

            exit_work_mode(SYS_WM_UDISK_MODE);

            break;
#endif

        default:
            return; /* No mode change */
        }

        enter_mode_wave_and_action(app_h->sys_work_mode, enter_work_mode);
    }
#endif
}

int system_work_mode_change_button(void)
{
    uint32_t last_mode;
    app_handle_t app_h = app_get_sys_handler();
    os_printf("system_work_mode_change_button\r\n");

    jtask_stop(app_h->app_common_task);

    last_mode = app_h->sys_work_mode;
#ifdef CONFIG_APP_SDCARD
btn:
#endif
    app_h->sys_work_mode++;
    if (app_h->sys_work_mode >= SYS_WM_NULL)
    {
        app_h->sys_work_mode = SYS_WM_BT_MODE;
    }
#ifdef CONFIG_APP_SDCARD
    else if (app_h->sys_work_mode == SYS_WM_SD_MUSIC_MODE)
    {
        if (!sd_is_attached())
            goto btn;
    }
#endif
#if (CONFIG_APP_USB_DISK)
    else if (app_h->sys_work_mode == SYS_WM_UDISK_MODE)
    {
        if (!sd_is_attached())
            goto btn;
    }
#endif

    os_printf("sys_work_mode:%d\r\n", app_h->sys_work_mode);

    exit_work_mode(last_mode);
    enter_mode_wave_and_action(app_h->sys_work_mode, enter_work_mode);
    return 0;
}

void exit_work_mode(uint32_t mode)
{
    app_handle_t app_h = app_get_sys_handler();

    switch (mode)
    {
#if (CONFIG_APP_MP3PLAYER == 1)
    case SYS_WM_SD_MUSIC_MODE:
        app_player_play_pause_caller(0);
        Delay(1000);
        app_player_unload();
        break;
#endif
    case SYS_WM_BT_MODE:
        if (app_bt_flag1_get(APP_FLAG_AVCRP_PROCESSING)) // AVRCP is processing
        {
            os_printf("Can not disconnect BT!\r\n");
        }
        else
        {
#if (defined(BT_SD_MUSIC_COEXIST))
            app_bt_flag1_set(APP_FLAG_AUTO_CONNECTION, 1);

            app_button_stop_action();

            os_printf("app_button_stop_action!\r\n");
#else
            app_bt_flag1_set(APP_FLAG_AUTO_CONNECTION, 0);

            app_button_playpause_action_caller(0); //off audio stream

            if (app_bt_flag1_get(APP_FLAG_ACL_CONNECTION))
            {
                if (a2dp_has_connection() && !avrcp_has_connection())
                {
                    app_bt_acl_time_out_wrap(); // To work around the case where AVRCP could not finish due to BT timeout
                }
                else
                {
                    app_button_conn_disconn_caller();
                }
            }

            // Disable BT scan
            bt_unit_set_scan_enable(app_h->unit, 0);
            jtask_stop(app_h->app_auto_con_task);
            jtask_stop(app_h->app_reset_task);
#endif
        }
        break;

#ifdef CONFIG_APP_USB_DISK
    case SYS_WM_UDISK_MODE:
        app_udisk_uninstall();
        break;
#endif

    default:
        break;
    }
}

void enter_work_mode(void)
{
    app_handle_t app_h = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();

    switch (app_h->sys_work_mode)
    {
    case SYS_WM_BT_MODE:
#if (!defined(BT_SD_MUSIC_COEXIST))
        app_bt_acl_time_out_wrap();
#endif

        if (env_h->env_cfg.bt_para.bt_flag & APP_ENV_BT_FLAG_AUTO_CONN)
        {
            app_bt_flag1_set(APP_FLAG_AUTO_CONNECTION, 1);
        }

        Delay(1000); // Let HW cool down before operate BT
        app_bt_button_setting();
        /* sbc_target_init_malloc_buff(); */

        if (!app_bt_flag1_get(APP_FLAG_ACL_CONNECTION))
        {
            app_button_conn_disconn_caller();
        }

#if (defined(BT_SD_MUSIC_COEXIST))
        if ((app_bt_flag1_get(APP_FLAG_MUSIC_PLAY)) && (app_bt_flag1_get(APP_BUTTON_FLAG_PLAY_PAUSE)))
        {
            aud_dac_open();
            extPA_open(0);
        }
        else
        {
            os_printf("F:%p:%p\r\n", (app_bt_flag1_get(APP_FLAG_MUSIC_PLAY)),
                      (app_bt_flag1_get(APP_BUTTON_FLAG_PLAY_PAUSE)));
        }
#endif
        break;

    case SYS_WM_SD_MUSIC_MODE:
        jtask_schedule(app_common_get_task_handle(), 100, sd_start_task, NULL);
        break;

#ifdef CONFIG_APP_USB_DISK
    case SYS_WM_UDISK_MODE:
        jtask_schedule(app_common_get_task_handle(), 500, app_udisk_install, NULL);
        break;
#endif

    default:
        break;
    }
}

unsigned int get_app_mode()
{
    app_handle_t app_h = app_get_sys_handler();
    return (app_h->sys_work_mode);
}

unsigned int get_bt_mode()
{
    app_handle_t app_h = app_get_sys_handler();
    return (app_h->bt_mode);
}

void set_bt_mode(unsigned int mode)
{
    app_handle_t app_h = app_get_sys_handler();
    app_h->bt_mode = mode;

    LOG_D(APP, "set bt_mode to %d\r\n", mode);
}

uint32_t app_is_mp3_mode(void)
{
    app_handle_t app_h = app_get_sys_handler();

    return (SYS_WM_SD_MUSIC_MODE == app_h->sys_work_mode);
}

uint32_t app_is_bt_mode(void)
{
    app_handle_t app_h = app_get_sys_handler();

    return (SYS_WM_BT_MODE == app_h->sys_work_mode);
}

#ifdef BT_SD_MUSIC_COEXIST
uint32_t player_runing_status = 0;
#endif

void app_incoming_call_enter(void)
{
#if (defined(BT_SD_MUSIC_COEXIST))
    app_handle_t app_h = app_get_sys_handler();
#endif

#ifdef BT_SD_MUSIC_COEXIST
    if (SYS_WM_SD_MUSIC_MODE == app_h->sys_work_mode)
    {
        os_printf("exit_mp3_\r\n");

        if (player_get_play_status())
        {
            player_runing_status = 1;
            app_player_play_pause_caller(0);
        }
        else
        {
            player_runing_status = 0;
        }

        Delay(1000);
        app_player_unload_for_incoming_call();

        /* sbc_target_init_malloc_buff(); */
    }
#endif
}

void incoming_call_exit(void *arg)
{
#if (defined(BT_SD_MUSIC_COEXIST))
    app_handle_t app_h = app_get_sys_handler();
#endif

#ifdef BT_SD_MUSIC_COEXIST
    if (SYS_WM_SD_MUSIC_MODE == app_h->sys_work_mode)
    {
        aud_dac_close();

#ifdef CONFIG_APP_AEC
        app_aec_uninit();
#endif

        os_printf("enter-mp3-\r\n");

        sbc_target_deinit_jfree_buff();

        app_player_load_for_incoming_call();

        /*play mp3_sd, after hang up*/
        if (player_runing_status)
        {
            app_player_play_pause_caller(1);
        }
    }
#endif
}

void app_incoming_call_exit(void)
{
#if (defined(BT_SD_MUSIC_COEXIST))
    app_handle_t app_h = app_get_sys_handler();
    jtask_stop(app_h->app_coexist_task);

    jtask_schedule(app_h->app_coexist_task, 3000, incoming_call_exit, NULL);
#endif
}

#if A2DP_ROLE_SOURCE_CODE
extern uint8_t get_a2dp_role(void);
void app_bt_sdp_connect(void)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();
    btaddr_t *remote_btaddr = &sys_hdl->remote_btaddr;
    btaddr_t *local_btaddr = &env_h->env_cfg.bt_para.device_addr;

    os_printf("app_bt_sdp_connect, local = " BTADDR_FORMAT ", remote = " BTADDR_FORMAT "\r\n", BTADDR(local_btaddr), BTADDR(remote_btaddr));

    sdp_connect(local_btaddr, remote_btaddr);
}

void app_bt_sdp_service_connect(void)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();
    btaddr_t *remote_btaddr = &sys_hdl->remote_btaddr;
    btaddr_t *local_btaddr = &env_h->env_cfg.bt_para.device_addr;

    os_printf("app_bt_sdp_service_connect, local = " BTADDR_FORMAT ", remote = " BTADDR_FORMAT "\r\n", BTADDR(local_btaddr), BTADDR(remote_btaddr));

    sdp_service_connect(local_btaddr, remote_btaddr, TID_A2DP_PROTOCOL_SSA_REQUEST);
}

void appBtStereoProfileConnWrap(void)
{
    app_handle_t app_h = app_get_sys_handler();
    app_env_handle_t env_h = app_env_get_handle();
    MSG_T msg;

    os_printf("app_bt_stereo_profile_conn_wrap\r\n");

    jtask_stop(app_h->app_auto_con_task);

    app_bt_flag2_set(APP_FLAG2_STEREO_WORK_MODE, 1);
    app_bt_flag2_set(APP_FLAG2_STEREO_BUTTON_PRESS | APP_FLAG2_STEREO_CONNECTTING | APP_FLAG2_STEREO_AUTOCONN, 0);

    app_bt_active_conn_profile(PROFILE_ID_AVRCP_CT, (void *)&app_h->stereo_btaddr);

    if (!a2dp_has_connection())
        bt_unit_set_scan_enable(app_h->unit, HCI_INQUIRY_SCAN_ENABLE | HCI_PAGE_SCAN_ENABLE);

    memcpy((uint8_t *)&env_h->env_data.default_btaddr, (uint8_t *)&app_h->remote_btaddr, sizeof(btaddr_t));

    msg.id = MSG_ENV_WRITE_ACTION;
    msg.arg = 0x01;
    msg.hdl = 0;
    msg_lush_put(&msg);

    //if(!a2dp_has_connection() && !hfp_has_connection())
    //app_set_led_event_action(LED_EVENT_MATCH_STATE);

    app_bt_flag2_set(APP_FLAG2_MATCH_BUTTON | APP_FLAG2_STEREO_MATCH_BUTTON, 0);
}

#define con_sync_start_flag 7
#define con_audio_interval_xms(val) (val * 32 / 10)

extern void lineinSbcEncodeInit(void);
extern void lineinSbcEncodeDestroy(void);

extern void sbcSrcNumSet(uint8_t num);
extern void open_linein2aux_loop(void);
extern result_t a2dpSrcCmdStreamStart(void);
extern void aud_mic_mute(uint8_t enable);
extern BOOL isA2dpSrcConnected(void);

static BOOL s_is_startAuxTx = FALSE; /* FALSE: not start, TRUE: already started.  */
void setAuxTxStarted(void)
{
    s_is_startAuxTx = TRUE;
}

void unsetAuxTxStarted(void)
{
    s_is_startAuxTx = FALSE;
}

BOOL isAuxTxStarted(void)
{
    return s_is_startAuxTx;
}

uint8_t debug_trace;

void debugSetTraceVal(uint8_t val)
{
    debug_trace = val;
}

int8_t debugShowTrace(uint8_t val)
{
    static uint8_t show_cnt = 0, last_val;

    if (debug_trace == val)
    {
        if (last_val != val)
        {
            last_val = val;
            show_cnt = 0;
        }

        if (show_cnt <= 10)
        {
            show_cnt++;
            os_printf("%d", val);
        }
        return 1;
    }
    else
    {
        show_cnt = 0;
        return 0;
    }
    //os_printf("trace:%d\r\n",val);
}

void appStartLinein2SbcEncode(void)
{
    app_handle_t sys_hdl = app_get_sys_handler();
    os_printf("appStartLinein2SbcEncode\r\n");

    M510_set_clock(CPU_CLK_SEL, CPU_CLK_DIV);

    // s1. init sbc encode.
    lineinSbcEncodeInit();

    // s2. start stream.
    jtask_schedule(sys_hdl->app_auto_con_task, 500, (jthread_func)a2dpSrcCmdStreamStart, NULL);
}

void appExitLinein2SbcEncode(void)
{
    os_printf("appExitLinein2SbcEncode\r\n");

    // s1. Destroy sbc encode.
    lineinSbcEncodeDestroy();
}

void appStartAuxTx(void *arg)
{
    os_printf("appStartAuxTx, enter..., %d\r\n", isA2dpSrcConnected());

    if (isA2dpSrcConnected() && (get_a2dp_role() == A2DP_ROLE_AS_SRC))
    {
        os_printf("appStartAuxTx, a2dp_role = SRC\r\n");

        setAuxTxStarted();

        // 1. open linein
        M510_Ana_Line_enable(1);

        // 2. open adc.
        aud_mic_mute(1);
        aud_mic_open(1);

        // 3. start encode.
        appStartLinein2SbcEncode();

        app_bt_flag2_set(APP_FLAG_LINEIN, 1);
        app_bt_flag2_set(APP_FLAG2_STEREO_PLAYING, 1);
    }
    else
    {
        os_printf("appStartAuxTx, a2dp_role = %d \n", get_a2dp_role());
    }
}

void appExitAuxTx(void)
{
    os_printf("appExitAuxTx, enter, a2dp_role = %d, %d \r\n", get_a2dp_role(), isA2dpSrcConnected());

    if (isA2dpSrcConnected() && (get_a2dp_role() == A2DP_ROLE_AS_SRC))
    {
        os_printf("appExitAuxTx, EXEC, a2dp_role = SRC\r\n");

        unsetAuxTxStarted();

        app_bt_flag2_set(APP_FLAG2_STEREO_WORK_MODE, 0);
        app_bt_flag2_set(APP_FLAG2_STEREO_PLAYING, 0);

        // 1. close adc.
        //aud_mic_mute(1);
        //aud_mic_open(0);

        // 2. close encode.
        appExitLinein2SbcEncode();
    }
    else
    {
        os_printf("appExitAuxTx, a2dp_role = %d, %d \n", get_a2dp_role(), isA2dpSrcConnected());
    }
}

#endif

// EOF
